﻿using System;
using Adaptive.Foundation.Tokenizers;

namespace Adaptive.Foundation.Parsing
{
    /// <summary>
    /// Provides a class for implementing a representation of a parsing rule for a token
    /// or set of tokens.
    /// </summary>
    /// <remarks>
    /// 
    /// </remarks>
    public class ParsingTokenRule : AiObjectBase, ICloneable 
    {
        /*--------------------------------------------------------------------------------
         * Private Member Declarations
         *------------------------------------------------------------------------------*/
        #region Private Member Declarations
        /// <summary>
        /// Application order value.
        /// </summary>
        private int _order = -1;
        /// <summary>
        /// Level value.
        /// </summary>
        private int _level = -1;
        /// <summary>
        /// Rule that might supercede this one.
        /// </summary>
        private ParsingTokenRule _supercededBy;
        /// <summary>
        /// Token to which a rule is applied.
        /// </summary>
        private RawToken _token;
        /// <summary>
        /// List of tokens to which a rule is applied.
        /// </summary>
        private RawTokenCollection _tokenList;
        /// <summary>
        /// Text to display.
        /// </summary>
        private string _display = string.Empty;
        /// <summary>
        /// Name of the rule.
        /// </summary>
        private string _ruleName = string.Empty;
        #endregion

        /*--------------------------------------------------------------------------------
         * Constructor / Dispose Methods
         *------------------------------------------------------------------------------*/
        #region Constructor / Dispose Methods
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <remarks>
        /// This is the default constructor.
        /// </remarks>
        public ParsingTokenRule()
            : base()
        {
            _tokenList = new RawTokenCollection();
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ParsingTokenRule"/> class.
        /// </summary>
        /// <param name="name">The name assigned to the rule.</param>
        public ParsingTokenRule(string name)
            : base()
        {
            Name = name;
            _ruleName = name;
            _tokenList = new RawTokenCollection();
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="ParsingTokenRule"/> class.
        /// </summary>
        /// <param name="name">The name assigned to the rule.</param>
        /// <param name="displayText">The display text.</param>
        /// <param name="order">The order in which to process the rule.</param>
        /// <param name="level">The level at which the rule is applied.</param>
        public ParsingTokenRule(string name, string displayText, int order, int level)
            : base()
        {
            Name = name;
            _ruleName = name;
            _tokenList = new RawTokenCollection();
            _display = displayText;
            _order = order;
            _level = level;
        }
        /// <summary>
        /// Deallocates internally allocated objects.
        /// </summary>
        /// <param name="disposing">
        /// A value indicating whether the object is being disposed.
        /// </param>
        protected override void Dispose(bool disposing)
        {
            if ((!Disposed) && (disposing))
            {
                if (_tokenList != null)
                    _tokenList.Dispose();
            }

            _ruleName = null;
            _supercededBy = null;
            _token = null;
            _tokenList = null;
            _display = null;
            base.Dispose(disposing);
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Properties
         *------------------------------------------------------------------------------*/
        #region Public Properties
        /// <summary>
        /// Gets or sets the text to be displayed.
        /// </summary>
        /// <value>
        /// Display text for a UI.
        /// </value>
        public string Display
        {
            get { return _display; }
            set { _display = value; }
        }
        /// <summary>
        /// Gets or sets the rule name.
        /// </summary>
        /// <value>
        /// The name of the rule.
        /// </value>
        public string RuleName
        {
            get { return _ruleName; }
            set { _ruleName = value; }
        }
        /// <summary>
        /// Gets or sets a value indicating the sequence in the order in which the rule
        /// is to be applied.
        /// </summary>
        /// <value>
        /// An order sequence value.
        /// </value>
        public int Order
        {
            get { return _order; }
            set { _order = value; }
        }
        /// <summary>
        /// Gets or sets a value at what level of parsing the rule becomes active.
        /// </summary>
        /// <value>
        /// A level indicator for recursive parsing operations.
        /// </value>
        public int Level
        {
            get { return _level; }
            set { _level = value; }
        }
        /// <summary>
        /// Gets or sets a reference to a rule that supercedes the current rule.
        /// </summary>
        /// <value>
        /// A <see cref="ParsingTokenRule"/> instance.
        /// </value>
        public ParsingTokenRule SupercededBy
        {
            get { return _supercededBy; }
            set { _supercededBy = value; }
        }
        /// <summary>
        /// Gets or sets the reference to the token to which a rule is applied.
        /// </summary>
        /// <value>
        /// A <see cref="RawToken"/> instance, or <b>null</b> if the list is used.
        /// </value>
        public RawToken Token
        {
            get { return _token; }
            set { _token = value; }
        }
        /// <summary>
        /// Gets the reference to the list of internal tokens.
        /// </summary>
        /// <value>
        /// A list of <see cref="RawToken"/> instances to which a rule may be applied.
        /// </value>
        public RawTokenCollection TokenList
        {
            get { return _tokenList; }
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Methods / Functions
         *------------------------------------------------------------------------------*/
        #region Public Methods / Functions
        /// <summary>
        /// Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        /// A new object that is a copy of this instance.
        /// </returns>
        object ICloneable.Clone()
        {
            return this.Clone();
        }
        /// <summary>
        /// Creates a new object that is a copy of the current instance.
        /// </summary>
        /// <returns>
        /// A new <see cref="ParsingTokenRule"/> instance with identical property values.
        /// </returns>
        public virtual ParsingTokenRule Clone()
        {
            ParsingTokenRule returnValue = null;

            returnValue = new ParsingTokenRule();

            returnValue.RuleName = _ruleName;
            returnValue.Display = _display;
            returnValue.Level = _level;
            returnValue.Name = Name;
            returnValue.Order = _order;
            returnValue.SupercededBy = _supercededBy;
            returnValue.Token = _token;
            foreach (RawToken token in _tokenList)
                returnValue.TokenList.Add(token);
            
            return returnValue;
        }
        #endregion

    }
}